﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Optimus.Drivers
{
    public class ATA : Core.Device 
    {
        private const byte MaxSecCount = 1;
        public UInt16[] DataBuffer = new UInt16[256];
        private byte status = 0;
        private bool ReadIsOk = false;
        private bool WriteIsOk = false;
        public bool IRQReceived = false;

        public void Init()
        {
            //Primary Controller
            Cosmos.Core.INTs.SetIrqHandler(0x0E, HandleIRQ);;
            Write8(0x1F6, 0xE0);//Enable IRQs
            Write8(0x3F6, 0x00);//Enable IRQs
        }
           
        public void PrintBuffer()
        {
            for (int p = 0; p < 256; p++)
            {
                if (p != 255)
                {
                    Console.Write(DataBuffer[p].ToString() + ",");
                }
                else
                {
                    Console.WriteLine(DataBuffer[p].ToString());
                }
            }
        }

        public void HandleIRQ(ref Cosmos.Core.INTs.IRQContext aContext)
        {
            Console.WriteLine("IRQ14");
            IRQReceived = true;
        }

        public override UInt16[] ReadBlock(uint LBA)
        {
            Write8(0x1F6, (byte)(0xE0 | (1 << 4) | ((LBA >> 24) & 0x0F)));
            Write8(0x1F1, 0);//Not DMA
            Write8(0x1F2, MaxSecCount);
            Write8(0x1F3, (byte)LBA);
            Write8(0x1F4, (byte)(LBA >> 8));
            Write8(0x1F5, (byte)(LBA >> 16));
            Write8(0x1F7, 0x20);
        
            for (int i = 0; i < 100; i++)
            {
                status = Read8(0x1F7);
                if ((status & 0xff) != 0x1)
                {
                   ReadIsOk = true;
                   break;
                }
                else if (i == 99)
                {
                    //TimeOut
                }
            }
            if (ReadIsOk == true)
            {
                for (int i = 0; i < 256; i++)
                {
                    DataBuffer[i] = Read16(0x1F0);
                }
            }
            else
            {
                //Read Failed
            }
            return DataBuffer;
        }

        public override void WriteBlock(uint LBA,UInt16[] Data)
        {
            Write8(0x1F6, (byte)(0xE0 | (1 << 4) | ((LBA >> 24) & 0x0F)));
            Write8(0x1F1, 0);//Not DMA
            Write8(0x1F2, MaxSecCount);
            Write8(0x1F3, (byte)LBA);
            Write8(0x1F4, (byte)(LBA >> 8));
            Write8(0x1F5, (byte)(LBA >> 16));
            Write8(0x1F7, 0x30);
            for (int i = 0; i < 100; i++)
            {
                status = Read8(0x1F7);
                if ((status & 0xff) != 0x1)
                {
                    WriteIsOk = true;
                    break;
                }
                else if (i == 99)
                {
                    //TimeOut
                }
            }
            if (WriteIsOk == true)
            {
               
                for (int i = 0; i < 256; i++)
                {
                    Write16(0x1F0, Data[i]);
                    for (int x = 0; x < 1; x++) { };//Wait
                }
            }
            else
            {
                //Write Failed
            }
        }
    }
}
